// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace WordCount
{
    /// <summary>
    /// Interaction logic for CountStatusWindow.xaml
    /// </summary>
    public partial class CountStatusWindow : Window
    {
        private int m_numMappers;
        private int m_numReducers;
        private TextBox[] m_mapperTexts;
        private TextBox[] m_reducerTexts;
        private TextBox m_aggregatorText;
        private SynchronizationContext m_sc;

        private string[] m_mapperStatus;
        private string[] m_reducerStatus;
        private string m_aggregatorStatus;

        private DispatcherTimer m_dispatcherTimer;

        public CountStatusWindow(int numMappers, int numReducers)
        {
            InitializeComponent();

            m_sc = SynchronizationContext.Current;
            m_numMappers = numMappers;
            m_numReducers = numReducers;

            m_mapperStatus = new string[m_numMappers];
            m_reducerStatus = new string[m_numReducers];
            m_aggregatorStatus = null;

            // Set up our grids
            for (int i = 0; i < numMappers; i++)
            {
                MapperGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
            }
            for (int i = 0; i < numReducers; i++)
            {
                ReducerGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
            }
            AggregatorGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });

            // Now fill in the individual textboxes
            m_mapperTexts = new TextBox[numMappers];
            for (int i = 0; i < numMappers; i++)
            {
                m_mapperTexts[i] = new TextBox()
                {
                    Text = "",
                    HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
                    VerticalAlignment = System.Windows.VerticalAlignment.Stretch,
                    HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center,
                    VerticalContentAlignment = System.Windows.VerticalAlignment.Center,
                    Margin = new Thickness(5),
                    Background = Brushes.Yellow,
                    IsReadOnly = true,
                    TextWrapping = TextWrapping.Wrap
                };
                MapperGrid.Children.Add(m_mapperTexts[i]);
                m_mapperTexts[i].SetValue(Grid.ColumnProperty, i);
            }

            m_reducerTexts = new TextBox[numReducers];
            for (int i = 0; i < numReducers; i++)
            {
                m_reducerTexts[i] = new TextBox()
                {
                    Text = "",
                    HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
                    VerticalAlignment = System.Windows.VerticalAlignment.Stretch,
                    HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center,
                    VerticalContentAlignment = System.Windows.VerticalAlignment.Center,
                    Margin = new Thickness(5),
                    Background = Brushes.LightGreen,
                    IsReadOnly = true,
                    TextWrapping = TextWrapping.Wrap
                };
                ReducerGrid.Children.Add(m_reducerTexts[i]);
                m_reducerTexts[i].SetValue(Grid.ColumnProperty, i);
            }

            {
                m_aggregatorText = new TextBox()
                {
                    Text = "",
                    HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
                    VerticalAlignment = System.Windows.VerticalAlignment.Stretch,
                    HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center,
                    VerticalContentAlignment = System.Windows.VerticalAlignment.Center,
                    Margin = new Thickness(5),
                    Background = Brushes.LightPink,
                    IsReadOnly = true,
                    TextWrapping = TextWrapping.Wrap
                };
                AggregatorGrid.Children.Add(m_aggregatorText);
                m_aggregatorText.SetValue(Grid.ColumnProperty, 0);
            }

            m_dispatcherTimer = new DispatcherTimer(DispatcherPriority.Render);
            m_dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 25); // 25 ms period
            m_dispatcherTimer.Tick += m_dispatcherTimer_Tick;
            m_dispatcherTimer.Start();            
        }

        void m_dispatcherTimer_Tick(object sender, EventArgs e)
        {
            PerformUpdates();
        }

        public void UpdateMapperStatus(int mapperIndex, string text)
        {
            m_mapperStatus[mapperIndex] = text;
            //m_sc.Post(state =>
            //    {
            //        m_mapperTexts[mapperIndex].Text = text;
            //        this.InvalidateArrange();
            //    }, null);
            //this.Dispatcher.InvokeAsync( () =>
            //    {
            //        m_mapperTexts[mapperIndex].Text = text;
            //    });
        }

        public void UpdateReducerStatus(int reducerIndex, string text)
        {
            m_reducerStatus[reducerIndex] = text;
            //m_sc.Post(state =>
            //{
            //    m_reducerTexts[reducerIndex].Text = text;
            //    this.InvalidateArrange();
            //}, null);
            //this.Dispatcher.InvokeAsync( () =>
            //    {
            //        m_reducerTexts[reducerIndex].Text = text;
            //    });
        }

        public void UpdateAggregatorStatus(string text)
        {
            m_aggregatorStatus = text;
            //this.Dispatcher.InvokeAsync(() =>
            //    {
            //        m_aggregatorText.Text = text;
            //    });
        }

        internal void PerformUpdates()
        {
            //this.Dispatcher.Invoke( () =>
            //{
                for(int i=0; i<m_numMappers; i++)
                {
                    m_mapperTexts[i].Text = m_mapperStatus[i];
                }

                for(int i=0; i<m_numReducers; i++)
                {
                    m_reducerTexts[i].Text = m_reducerStatus[i];
                }

                m_aggregatorText.Text = m_aggregatorStatus;
            //});
        }
    }
}
